﻿using AutoMapper;
using Quartz;
using SXFramWork.Core;
using SXFramWork.Core.Quartz;
using SXFramWork.Model;
using SXFramWork.Repository;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace SXFramWork.Service
{
    public class SysJobService:ISysJobService
    {
        private readonly ISysJobRepository _repository;
        private readonly IMapper _mapper;
        private readonly ISysJobLogRepository _logRepository;
        private readonly IQuartzCenter _quartzServer;
        public SysJobService(ISysJobRepository sysJobRepository,IMapper mapper,IQuartzCenter quartzCenter,ISysJobLogRepository sysJobLogRepository)
        {
            _logRepository = sysJobLogRepository;
            _quartzServer = quartzCenter;
            _mapper = mapper;
            _repository = sysJobRepository;
        }

        public async Task<IApiResult> Add(JobAddModel model)
        {
            var entity = _mapper.Map<SysJobEntity>(model);
            entity.JobKey = $"{model.Group}.{model.Code}";
            entity.Status = 0;
            entity.Id = GuidHelper.NewSequentialGuid(SequentialGuidType.SequentialAtEnd);
            entity.CreateTime = DateTime.Now;
            if (await _repository.ExistsAsync(entity.Id,"sysjob"))
            {
                return ApiResult.NotOk($"当前任务组{entity.Group}已存在任务编码{entity.Code}");
            }
            ////是否立即启动
            //if (model.Start)
            //{
            //    var result = await AddJob(entity);
            //    if (!result.Successful)
            //    {
            //        return result;
            //    }
            //    entity.Status = JobStatus.Running;
            //}
            var res= await _repository.InsertAsync(entity);
            if(res.IsNull())
                return ApiResult.NotOk("任务添加失败");
            return ApiResult.Ok();
        }

        public async Task<IApiResult> Delete(string id)
        {
            var entity = await _repository.GetAsync(id);
            if (entity == null)
            {
                return ApiResult.NotOk("任务不存在");
            }

            if (entity.Status != 0 && entity.Status != 3)
            {
                var jobKey = new JobKey(entity.Code, entity.Group);
                await _quartzServer.DeleteJob(jobKey);
            }
            var result = await _repository.DeleteAsync(entity);

            return ApiResult.Result(result);
        }

        public async Task<IApiResult> Log(JobLogQueryModel model)
        {
            var result = new PageResult<SysJobLogEntity>
            {
                Rows = await _logRepository.Query(model),
                TotalCount = model.TotalCount
            };
            return ApiResult.Ok(result);
        }

        public async Task<IApiResult> Pause(string id)
        {
            var entity = await _repository.GetAsync(id);
            if (entity == null)
            {
                return ApiResult.NotOk("任务不存在");
            }

            if (entity.Status ==0)
            {
                return ApiResult.NotOk("任务已停止，无法暂停");
            }

            if (entity.Status ==3)
            {
                return ApiResult.NotOk("任务已完成，无法暂停");
            }

            if (entity.Status == 2)
            {
                return ApiResult.NotOk("任务已暂停，请刷新页面");
            }
            entity.Status = 2;
            await SetStatus(entity);
            var jobKey = new JobKey(entity.Code, entity.Group);
            await _quartzServer.PauseJob(jobKey);

            return ApiResult.Ok();
        }

        public async Task<IApiResult> Query(JobQueryModel model)
        {
            var result = new PageResult<SysJobEntity>
            {
                Rows = await _repository.Query(model),
                TotalCount = model.TotalCount
            };
            return ApiResult.Ok(result);
        }

        public async Task<IApiResult> Resume(string id)
        {
            try
            {
                var entity = await _repository.GetAsync(id);
                if (entity == null)
                    return ApiResult.NotOk("该任务不存在");
                if (entity.Status == 1)
                    return ApiResult.NotOk("任务已在运行，请刷新页面");

                //停止的或者已完成的任务，重启需要重新加入到调度中
                if (entity.Status == 0 || entity.Status == 3)
                {
                    if (entity.EndTime <= DateTime.Now)
                    {
                        return ApiResult.NotOk("任务时效已过期");
                    }

                    var result = await AddJob(entity, true);
                    if (!result.Success)
                    {
                        return result;
                    }
                }
                else
                {
                    var jobKey = new JobKey(entity.Code, entity.Group);
                    await _quartzServer.ResumeJob(jobKey);
                }
                entity.Status = 1;
                await SetStatus(entity);
                return ApiResult.Ok();
            }
            catch(Exception ex)
            {
                return ApiResult.NotOk(ex.Message);
            }

        }

        public async Task<IApiResult> Stop(string id)
        {
            var entity = await _repository.GetAsync(id);
            if (entity == null)
            {
                return ApiResult.NotOk("任务不存在");
            }

            if (entity.Status == 0)
            {
                return ApiResult.NotOk("任务已停止，请刷新页面");
            }
            if (entity.Status == 3)
            {
                return ApiResult.NotOk("任务已完成，无法停止");
            }
            entity.Status = 0;
            await SetStatus(entity);
            var jobKey = new JobKey(entity.Code, entity.Group);
            await _quartzServer.DeleteJob(jobKey);
            return ApiResult.Ok();
        }

        /// <summary>
        /// 添加任务
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="start">是否立即启动</param>
        /// <returns></returns>
        private async Task<IApiResult> AddJob(SysJobEntity entity, bool start = false)
        {
            var jobClassType =System.Type.GetType(entity.JobClass);
            if (jobClassType == null)
            {
                return ApiResult.NotOk($"任务类({entity.JobClass})不存在");
            }

            var jobKey = new JobKey(entity.Code, entity.Group);
            var job = JobBuilder.Create(jobClassType).WithIdentity(jobKey)
                .UsingJobData("id", entity.Id.ToString()).Build();

            var triggerBuilder = TriggerBuilder.Create().WithIdentity(entity.Code, entity.Group)
                .EndAt(entity.EndTime.ToUniversalTime())
                .WithDescription(entity.Name);

            //如果开始日期小于等于当前日期则立即启动
            if (entity.StartTime <= DateTime.Now)
            {
                triggerBuilder.StartNow();
            }
            else
            {
                triggerBuilder.StartAt(entity.StartTime.ToUniversalTime());
            }

            if (entity.TriggerType == 0)
            {
                //简单任务
                triggerBuilder.WithSimpleSchedule(builder =>
                {
                    builder.WithIntervalInSeconds(entity.Interval);
                    if (entity.RepeatCount > 0)
                    {
                        builder.WithRepeatCount(entity.RepeatCount - 1);
                    }
                    else
                    {
                        builder.RepeatForever();
                    }
                });
            }
            else
            {
                if (!CronExpression.IsValidExpression(entity.Cron))
                {
                    return ApiResult.NotOk("CRON表达式无效");
                }

                //CRON任务
                triggerBuilder.WithCronSchedule(entity.Cron);
            }

            var trigger = triggerBuilder.Build();
            try
            {
                await _quartzServer.AddJob(job, trigger);

                if (!start)
                {
                    //先暂停
                    await _quartzServer.PauseJob(jobKey);
                }

                return ApiResult.Ok();
            }
            catch (Exception ex)
            {
                Loghelper.Default.writelog($"任务调度添加任务失败{ @ex}");
            }
            return ApiResult.NotOk();
        }
        /// <summary>
        /// 更改任务状态
        /// </summary>
        /// <param name="Status"></param>
        /// <param name="id"></param>
        private async Task SetStatus(SysJobEntity entity)
        {
            await _repository.UpdateAsync(entity);
        }


    }
}
